#ifndef _LIBRARY_H_
#define _LIBRARY_H_

class Book_t;
class Borrower_t;

typedef unsigned long long ull;

#include <list>
#include <map>
#include <string>

class Library_t
{
public:

	/**
	* CTOR
	*/
	Library_t();

	/**
	* DTOR
	*/
	virtual ~Library_t();

	/**
	* Add new book to the library
	*/
	bool addBook(Book_t* const book);

	/**
	* Removes a book from the library
	*/
	bool removeBook(const Book_t* book, bool del=false);


	/**
	* Add new borrower to the library
	* Return borrower's ID on success, 0 on failure (i.e. borrower already exists)
	*/
	unsigned long addBorrower(Borrower_t* const borrower);

	/**
	* Removes a borrower from the library
	*/
	bool removeBorrower(const Borrower_t* borrower, bool del=false);

	/**
	* Return true if book already exists in library
	*/
	bool bookExists(const Book_t* book) const;

	/**
	* Return true if borrower already exists in library
	*/
	bool borrowerExists(const Borrower_t* borrower) const;

	/**
	* find a book by ISBN
	*/
	Book_t* findBook(ull ISBN) const;

	/**
	* find a borrower by ID
	*/
	Borrower_t* findBorrower(unsigned long id) const;

	/**
	* Returns 1 on success
	* Returns 0 when added to waiting list
	* Returns -1 on error (book / borrower not found or book is already borrowed by reader)
	*/
	virtual int borrow(Borrower_t* const borrower, Book_t* const book);

	/**
	* Returns 1 on success
	* Returns 0 if by returning the book it was automatically given to another user
	* Returns -1 on error (book / borrower not found or book is not borrowed by the reader)
	*/
	virtual int returnBook(Borrower_t* borrower, Book_t* book);

	/**
	* Book report
	*/
	virtual std::string bookReport() const;

	/**
	* Borrower report
	*/
	virtual std::string borrowerReport() const;


private:
	/**
	* Map of book in the library
	*/

	typedef std::map<ull, Book_t*> booksMap;
	booksMap m_booksMap;

	/**
	* Map of borrowers
	*/
	typedef std::map<unsigned long, Borrower_t*> borrowersMap;
	borrowersMap m_borrowersMap;

	/**
	* COPY CTOR
	*/
	Library_t(const Library_t& other);

	/**
	* Operator=
	*/
	Library_t& operator=(const Library_t& other);

};

#endif
